package com.ruoyi.service.project.service.impl;


import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.service.project.entity.ProjectEntity;
import com.ruoyi.service.project.entity.ProjectLaborEntity;
import com.ruoyi.service.project.enums.HireStatusEnum;
import com.ruoyi.service.project.enums.ProjectStatusEnum;
import com.ruoyi.service.project.mapper.ProjectLaborMapper;
import com.ruoyi.service.project.model.LaborCount;
import com.ruoyi.service.project.service.ProjectLaborService;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;
import org.springframework.stereotype.Service;

/**
 * <p>
 * 项目岗位招聘情况 服务实现类
 * </p>
 *
 * @author Zane
 * @since 2025-10-14
 */
@Service
public class ProjectLaborServiceImpl extends ServiceImpl<ProjectLaborMapper, ProjectLaborEntity>
    implements ProjectLaborService {

  @Override
  public List<ProjectLaborEntity> getHiredByProjectId(String projectId) {
    return list(effectQuery().eq(ProjectLaborEntity::getProjectId, projectId)
        .in(ProjectLaborEntity::getStatus, HireStatusEnum.getHiredStatus())
    );
  }

  @Override
  public List<ProjectLaborEntity> couldHiredByProjectId(String projectId) {
    return list(effectQuery().eq(ProjectLaborEntity::getProjectId, projectId)
        .eq(ProjectLaborEntity::getStatus, HireStatusEnum.WAIT_AUDIT)
    );
  }

  @Override
  public List<ProjectLaborEntity> getWorkingLaborByProjectId(String projectId) {
    return list(effectQuery().eq(ProjectLaborEntity::getProjectId, projectId)
        .eq(ProjectLaborEntity::getStatus, HireStatusEnum.HIRE_PASS.getCode()));
  }

  @Override
  public long countByLaborIdAndProjectId(Long laborId, String projectId) {
    return count(effectQuery().eq(ProjectLaborEntity::getProjectId, projectId)
        .eq(ProjectLaborEntity::getLaborId, laborId)
    );
  }

  @Override
  public Long countUserInProjectPost(String projectId, Long laborId, String postName) {
    return count(effectQuery().eq(ProjectLaborEntity::getProjectId, projectId)
        .eq(ProjectLaborEntity::getLaborId, laborId)
        .eq(ProjectLaborEntity::getPostName, postName)
    );
  }

  @Override
  public List<String> getCompleteProject(Long userId) {
    return Optional.ofNullable(list(effectQuery().eq(ProjectLaborEntity::getLaborId, userId)
            .in(ProjectLaborEntity::getStatus, HireStatusEnum.getHiredStatus())))
        .orElseGet(ArrayList::new).stream()
        .map(ProjectLaborEntity::getProjectId).distinct().collect(Collectors.toList());
  }

  @Override
  public List<String> getApplyProject(Long userId) {
    // TODO 这里在项目数据量激增的时候会形成性能瓶颈,目前情况暂不得已,后续可以根据情况将子查询上移到ProjectService
    final String sqlSub = new LambdaQueryWrapper<ProjectEntity>().select(ProjectEntity::getId)
        .eq(ProjectEntity::getStatus, ProjectStatusEnum.PUBLISH.getCode())
        .gt(ProjectEntity::getProjectStart, LocalDateTime.now()).getSqlSelect();
    return Optional.ofNullable(list(effectQuery().eq(ProjectLaborEntity::getLaborId, userId)
            .in(ProjectLaborEntity::getProjectId, sqlSub))
        )
        .orElseGet(ArrayList::new).stream()
        .map(ProjectLaborEntity::getProjectId).distinct().collect(Collectors.toList());
  }

  @Override
  public List<String> getExecutionCount(Long userId) {
    // TODO 这里在项目数据量激增的时候会形成性能瓶颈,目前情况暂不得已,后续可以根据情况将子查询上移到ProjectService
    final String sqlSub = new LambdaQueryWrapper<ProjectEntity>().select(ProjectEntity::getId)
        .eq(ProjectEntity::getStatus, ProjectStatusEnum.ON_EXECUTION.getCode())
        //为了命中索引
        .lt(ProjectEntity::getProjectStart, LocalDateTime.now())
        .gt(ProjectEntity::getProjectEnd, LocalDateTime.now())
        .getSqlSelect();
    return Optional.ofNullable(list(effectQuery().eq(ProjectLaborEntity::getLaborId, userId)
            //.in(ProjectLaborEntity::getStatus, HireStatusEnum.getHiredStatus())
            .in(ProjectLaborEntity::getProjectId, sqlSub))
        )
        .orElseGet(ArrayList::new).stream()
        .map(ProjectLaborEntity::getProjectId).distinct().collect(Collectors.toList());
  }

  @Override
  public Map<String, Long> getProjectLaborCountMap(List<String> projectIdList) {
    if (CollUtil.isEmpty(projectIdList)) {
      return new HashMap<>();
    }
    return Optional.ofNullable(
            this.getBaseMapper().getProjectLaborCountMap(projectIdList)).orElseGet(ArrayList::new)
        .stream()
        .collect(
            Collectors.toMap(LaborCount::getProjectId, LaborCount::getLaborCount, (v1, v2) -> v1))
        ;
  }

  private LambdaQueryWrapper<ProjectLaborEntity> effectQuery() {
    return new LambdaQueryWrapper<>();
  }
}
